<template>
  <component
    :id="mConfig.id"
    class="page-draggable-dom not-select"
    :class="[
      setting.isDraggable || setting.showPageDomSubline ? 'subline' : '',
      dropPosition ? 'drop-position-' + dropPosition : ''
    ]"
    :is="'page-node-dom'"
    :mConfig="mConfig"
    :draggable="true"
    @click.stop.native="event => pageDomClickHandle(event)"
    @dragover.native="event => draggableHandle('dragover', event)"
    @dragleave.native="event => draggableHandle('dragleave', event)"
    @drop.native="event => draggableHandle('drop', event)"
    @dragstart.native="event => draggableHandle('dragstart', event)"
    @dragend.native="event => draggableHandle('dragend', event)"
  >
    <template v-for="(item, index) in mConfig.children">
      <page-draggable-dom
        :mConfig.sync="mConfig.children[index]"
        :parent="mConfig"
        :key="index"
        :selectItemKey="selectItemKey"
      ></page-draggable-dom>
    </template>
  </component>
</template>

<script>
import PageNodeDom from './PageNodeDom.vue'
import setting from '@/store/setting'
import _ from 'lodash'
import { initDomValue, isCanPushChildren, selectItem } from '@/util/pageUtil'

export default {
  name: 'PageDraggableDom',
  components: {
    PageNodeDom
  },
  props: {
    // 页面配置
    mConfig: {
      type: Object,
      default() {
        return {}
      }
    },
    // 父元素，用于拖放元素
    parent: {
      type: Object
    },
    // 点击选中item的key
    selectItemKey: {
      type: String,
      default() {
        return 'item'
      }
    }
  },
  inject: ['selectPageNodeDom'],
  data() {
    return {
      setting: setting,
      // 元素:top-顶部;in-内部;bottom-底部
      dropPosition: ''
    }
  },
  methods: {
    // PageDom点击事件
    pageDomClickHandle(event) {
      this.setItem(this.mConfig)
    },
    // 处理拖拽事件
    draggableHandle(type, event) {
      switch (type) {
        // 1.开始拖拽
        case 'dragstart':
          setting.isDraggable = true
          this.selectPageNodeDom.dragItem = this.mConfig
          break
        // 4.结束拖拽
        case 'dragend':
          setting.isDraggable = false
          if (this.selectPageNodeDom.dragFlag === true) {
            this.parent.children.splice(this.parent.children.indexOf(this.selectPageNodeDom.dragItem), 1)
          }
          this.selectPageNodeDom.dragItem = {}
          this.selectPageNodeDom.dragFlag = false
          break
        // 2.元素拖动时触发
        case 'dragover':
          const height = event.target.getBoundingClientRect().height
          const offsetY = event.offsetY
          const percent = offsetY / height
          // 元素:top-顶部;in-内部;bottom-底部
          if (percent < 0.2) {
            this.dropPosition = 'top'
          } else if (percent > 0.8) {
            this.dropPosition = 'bottom'
          } else {
            this.dropPosition = 'in'
          }
          if (this.setting.isDraggable && this.selectPageNodeDom.dragItem !== this.mConfig) {
            event.preventDefault()
          }
          break
        // 元素离开当前dom
        case 'dragleave':
          this.dropPosition = ''
          break
        // 3.拖拽元素放下
        case 'drop':
          // 检查是否符合拖动元素配置的规则
          const targetItem = this.dropPosition === 'in' ? this.mConfig : this.parent || this.mConfig
          if (isCanPushChildren(targetItem, this.selectPageNodeDom.dragItem)) {
            const tmp = _.cloneDeep(this.selectPageNodeDom.dragItem)
            // 初始化默认值
            initDomValue(tmp)
            // 如果是拖拽到元素顶部区域
            const targetIndex = targetItem.children.indexOf(this.mConfig)
            if (this.dropPosition === 'top') {
              targetItem.children.splice(targetIndex, 0, tmp)
            } else if (targetIndex !== -1 && this.dropPosition === 'bottom') {
              targetItem.children.splice(targetIndex + 1, 0, tmp)
            } else {
              targetItem.children.push(tmp)
            }
            // this.$emit('update:mConfig', this.mConfig)
            this.setItem({})
            this.setItem(tmp)
            this.selectPageNodeDom.dragFlag = true
          }
          this.dropPosition = ''
          break
      }
      event.stopPropagation()
    },
    setItem(item) {
      if (this.selectItemKey === 'item') {
        selectItem(this.selectPageNodeDom, item)
      } else {
        selectItem(this.selectPageNodeDom, this.selectPageNodeDom.item, item)
      }
    }
  }
}
</script>

<style lang="less">
.page-draggable-dom {
  // width: 100%;
  min-width: 10px !important;
  min-height: 10px !important;
  position: relative;
  // border: 1px solid #000000;
  // outline: #40a9ff solid 2px;
  // min-height: 10px;
  &.draggable {
    min-height: 10px;
  }
  // 辅助线
  &.subline {
    outline: 1px dashed #67cded;
  }
  &.drop-position {
    // 元素:top-顶部;in-内部;bottom-底部
    &-top::before,
    &-bottom::after {
      position: absolute;
      content: ' ';
      display: block;
      width: 100%;
      height: 3px;
      background-color: #2d88f8;
      left: 0;
    }
    &-top::before {
      top: -3px;
    }
    &-in {
      outline: 3px solid #2d88f8;
    }
    &-bottom::after {
      bottom: -3px;
    }
  }
}
</style>
